/*
 * simple FIFO handling
 *
 * Copyright (C) 2008  Bartlomiej Zolnierkiewicz
 *
 * TODO:
 * - fifo_realloc()
 */

#include <malloc.h>

#include "fifo.h"

#include "cbr_debug.h"	/* for cbr_log() */

fifo_t *fifo_alloc(int size)
{
	fifo_t *fifo;

	fifo = (fifo_t *)malloc(sizeof(*fifo));
	if (fifo == NULL)
		goto out;

	fifo->q = (void **)malloc(sizeof(void *) * size);
	if (fifo->q == NULL) {
		free(fifo);
		goto out;
	}

	fifo->size = size;
	fifo->first = fifo->last = fifo->count = 0;
out:
	return fifo;
}

void fifo_free(fifo_t *fifo)
{
	free(fifo->q);
	free(fifo);
}

void fifo_enqueue(fifo_t *fifo, void *data)
{
	if (fifo->count < fifo->size) {
		fifo->q[fifo->last] = data;
		fifo->last = (fifo->last + 1) % fifo->size;
		fifo->count++;
	} else
		cbr_log("Error: FIFO overflow\n");
}

void *fifo_dequeue(fifo_t *fifo)
{
	void *data = NULL;

	if (fifo->count > 0) {
		data = fifo->q[fifo->first];
		fifo->first = (fifo->first + 1) % fifo->size;
		fifo->count--;
	} else {
//		cbr_log("Error: trying to deqeueu from empty FIFO\n");
	}

	return data;
}

int fifo_empty(fifo_t *fifo)
{
	return fifo->count == 0;
}

int fifo_full(fifo_t *fifo)
{
	return fifo->count == fifo->size;
}

void fifo_dump(fifo_t *fifo)
{
	int i, j = fifo->first;

	cbr_log("FIFO: %p size=%d count=%d first=%d last=%d\n",
		fifo, fifo->size, fifo->count, j, fifo->last);

	for (i = 0; i < fifo->count; i++) {
		cbr_log("FIFO: [%d] %08x\n", i, (unsigned int)fifo->q[j]);
		j = (j + 1) % fifo->size;
	}
}
